#include "stdio.h"
#include "string.h"
#include "i2s_audio_recorder.h"
#include <inttypes.h> // 用于uint32_t格式化输出

/* 音频配置参数 - 根据实际需求调整 */
#define AUDIO_SAMPLE_RATE 44100 // 采样率：44.1kHz
#define AUDIO_CHANNELS    2     // 声道数：双声道
#define AUDIO_BIT_DEPTH   16    // 位深：16位
#define BUFFER_SIZE       512   // 缓冲区大小（样本数）- 512更稳定
#define MAX_FILE_NUMBER   64    // 最大文件编号限制

/* 函数声明 - 解决隐式声明冲突 */
const char *get_fatfs_error_desc(FRESULT res);

/* 全局变量 */
FATFS fs;                              // FATFS文件系统对象
FIL file;                              // 文件对象
uint16_t audio_buffer[BUFFER_SIZE];    // 16位PCM样本缓冲区
volatile uint8_t recording_active = 0; // 录音状态标志
volatile uint8_t buffer_ready     = 0; // 缓冲区就绪标志
volatile uint8_t current_buffer   = 0; // 当前处理的缓冲区（0:前半段 1:后半段）
char filename[20];

/* 查找下一个可用的文件名（wav_1.bin, wav_2.bin...） */
static FRESULT find_next_available_filename(char *filename)
{
    FRESULT fr;
    uint16_t file_num = 1;
    char temp_filename[20];
    FIL temp_file;

    // 从1开始查找未被使用的文件名
    while (file_num <= MAX_FILE_NUMBER) {
        // 格式化文件名（bin格式）
        sprintf(temp_filename, "wav_%d.bin", file_num);

        // 检查文件是否存在
        fr = f_open(&temp_file, temp_filename, FA_READ);
        if (fr == FR_NO_FILE) {
            // 找到可用文件名，复制到输出参数
            strcpy(filename, temp_filename);
            return FR_OK;
        } else if (fr == FR_OK) {
            // 文件已存在，关闭并尝试下一个编号
            f_close(&temp_file);
            file_num++;
        } else {
            // 其他错误（如磁盘错误）
            printf("File search error: %s\n", get_fatfs_error_desc(fr));
            return fr;
        }
    }

    // 达到最大文件编号限制
    printf("Exceeded maximum file limit: %d\n", MAX_FILE_NUMBER);
    return FR_TOO_MANY_OPEN_FILES;
}

/* 初始化音频录制系统 */
HAL_StatusTypeDef AudioRecorder_Init(void)
{
    // 初始化I2S接口
    if (HAL_I2S_GetState(&hi2s2) == HAL_I2S_STATE_RESET) {
        if (HAL_I2S_Init(&hi2s2) != HAL_OK) {
            printf("I2S initialization failed\n");
            return HAL_ERROR;
        }
    }

    // 初始化SD卡和FATFS文件系统
    FRESULT res = f_mount(&fs, "", 1);
    if (res != FR_OK) {
        printf("SD card mount failed: %s\n", get_fatfs_error_desc(res));
        return HAL_ERROR;
    }

    printf("Audio system initialized. Press key to start recording...\n");
    return HAL_OK;
}

/* 开始录制音频到bin文件（原始PCM数据） */
HAL_StatusTypeDef StartRecording(void)
{
    FRESULT res;
    

    // 查找下一个可用的文件名
    res = find_next_available_filename(filename);
    if (res != FR_OK) {
        printf("Failed to find available filename!\n");
        return HAL_ERROR;
    }

    // 创建bin文件（只写模式）
    res = f_open(&file, filename, FA_CREATE_ALWAYS | FA_WRITE);
    if (res != FR_OK) {
        printf("Failed to create file %s: %s\n", filename, get_fatfs_error_desc(res));
        return HAL_ERROR;
    }
    printf("Started recording to: %s\n", filename);

    // 启动I2S DMA接收（双缓冲区模式）
    if (HAL_I2S_Receive_DMA(&hi2s2, (uint16_t *)audio_buffer, BUFFER_SIZE) != HAL_OK) {
        f_close(&file);
        printf("I2S DMA start failed\n");
        return HAL_ERROR;
    }

    recording_active = 1; // 标记为正在录音
    return HAL_OK;
}

/* 停止录制 */
void StopRecording(void)
{
    if (!recording_active) return; // 未在录音则直接返回

    // 停止I2S DMA接收
    HAL_I2S_DMAStop(&hi2s2);

    // 强制刷新文件缓存到磁盘（确保数据写入完成）
    f_sync(&file);

    // 关闭文件
    f_close(&file);
    recording_active = 0; // 清除录音状态
    printf("Recording stopped\n");
}

/* 处理音频数据 - 将缓冲区数据写入SD卡 */
void ProcessAudioData(void)
{
    if (!buffer_ready || !recording_active) return;
    // 翻转LED指示灯，标记正在处理数据
    LED_B_Toggle();

    UINT bytes_written;  // 实际写入的字节数
    FRESULT res;         // FATFS操作结果
    uint32_t write_size; // 计划写入的字节数
    f_open(&file, filename, FA_CREATE_ALWAYS | FA_WRITE);
    // 计算写入大小：每个样本16位（2字节），根据当前缓冲区分段计算
    if (current_buffer == 0) {
        // 处理前半缓冲区
        write_size = (BUFFER_SIZE / 2) * 2; // 样本数 × 2字节/样本
        res        = f_write(&file, audio_buffer, write_size, &bytes_written);
    } else {
        // 处理后半缓冲区
        write_size = (BUFFER_SIZE / 2) * 2;
        res        = f_write(&file, audio_buffer + BUFFER_SIZE / 2, write_size, &bytes_written);
    }

    // 错误处理（带重试机制）- 修复格式符不匹配问题
    if (res != FR_OK || bytes_written != write_size) {
        printf("Write error: %s (Expected: %" PRIu32 " bytes, Wrote: %u bytes)\n",
               get_fatfs_error_desc(res), write_size, (unsigned int)bytes_written);

        // 重试一次
        if (res != FR_OK) {
            HAL_Delay(5); // 延迟5ms后重试
            if (current_buffer == 0) {
                res = f_write(&file, audio_buffer, write_size, &bytes_written);
            } else {
                res = f_write(&file, audio_buffer + BUFFER_SIZE / 2, write_size, &bytes_written);
            }
        }

        // 仍失败则停止录音
        if (res != FR_OK || bytes_written != write_size) {
            StopRecording();
        }
    }

    buffer_ready = 0; // 标记缓冲区已处理完成
}

/* I2S DMA半传输完成回调 - 处理前半缓冲区 */
void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{
    if (hi2s == &hi2s2 && recording_active) {
        current_buffer = 0; // 标记当前处理前半缓冲区
        buffer_ready   = 1; // 标记缓冲区就绪
        ProcessAudioData(); // 立即处理缓冲区数据
    }
}

/* I2S DMA传输完成回调 - 处理后半缓冲区 */
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
    if (hi2s == &hi2s2 && recording_active) {
        current_buffer = 1; // 标记当前处理后半缓冲区
        buffer_ready   = 1; // 标记缓冲区就绪
        ProcessAudioData(); // 立即处理缓冲区数据
    }
}

/* FATFS错误描述函数 - 将错误码转换为英文描述 */
const char *get_fatfs_error_desc(FRESULT res)
{
    static const char *fatfs_error_desc[] = {
        "Success", "Disk I/O error", "Internal error", "Drive not ready",
        "File not found", "Path not found", "Invalid filename", "Access denied",
        "File exists", "Invalid object", "Write protected", "Invalid drive",
        "Drive not enabled", "No filesystem", "MKFS aborted", "Timeout",
        "File locked", "Not enough core", "Too many open files"};

    if (res < 0 || res >= sizeof(fatfs_error_desc) / sizeof(fatfs_error_desc[0])) {
        return "Unknown error";
    }
    return fatfs_error_desc[res];
}
